home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i025: Check mailboxes for new mail
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Wayne Mesard <mesard@bbn.com>
- Posting-number: Volume 15, Issue 25
- Archive-name: ck
-
- These programs examine mailbox files and report the sender and subject of
- each message contained in the file. Although there are dozens of similar
- programs wandering around UNIX land, many don't work on common system
- configurations. (E.g., from only works if the mailbox lives in
- /usr/spool/mail ; buff and rcvalert don't get along well with the SunView
- windows; etc.)
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: Makefile ck.c ck.man ckd.man wsm_types.h
- # Wrapped by rsalz@fig.bbn.com on Tue May 31 16:20:42 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(155 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- BIN = ../bin/
- CFLAGS = -O
- X
- all: ck ckd
- X
- ck: $(BIN)ck
- X$(BIN)ck: ck.c
- X $(CC) $(CFLAGS) ck.c -o $(BIN)ck
- X
- ckd: $(BIN)ckd
- X$(BIN)ckd:
- X ln -s $(BIN)ck $(BIN)ckd
- END_OF_FILE
- if test 155 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'ck.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ck.c'\"
- else
- echo shar: Extracting \"'ck.c'\" \(4618 characters\)
- sed "s/^X//" >'ck.c' <<'END_OF_FILE'
- X/**************************************************************************
- X * ck{,d}: an incoming mail monitor.
- X * Copyright (c) 1988 Wayne Mesard *
- X * *
- X * This is free software. It may be reproduced, retransmitted, *
- X * redistributed and otherwise propogated at will, provided that *
- X * this notice remains intact and in place. *
- X * *
- X * Direct all bug reports and comments to mesard@BBN.COM. *
- X * *
- X **************************************************************************/
- X
- X
- X#include <stdio.h>
- X#include <strings.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <ctype.h>
- X#include "wsm_types.h"
- X
- X
- main(argc, argv)
- int argc;
- char *argv[];
- X{
- X extern char *getenv();
- X extern int atoi();
- X extern int getppid(); /* For parent check. */
- X int check_box();
- X time_t last_write();
- X
- X int i, c;
- X int interval = 120;
- X FILE *out_device = NULL;
- X boolean verbose = false;
- X int ppid; /* For parent check. */
- X
- X char *ptr, mailbox[256];
- X time_t curr, old_mtime;
- X
- X
- X for (i=0; ++i<argc && argv[i][0]=='-';)
- X switch (argv[i][1]) {
- X case 'v':
- X verbose = true;
- X break;
- X case 'i':
- X interval = atoi(argv[i]+2);
- X break;
- X case 'o':
- X if (out_device != NULL)
- X fclose(out_device);
- X if (i+1<argc)
- X if ((out_device = fopen(argv[++i], "a"))==NULL) {
- X perror(argv[i]+2);
- X exit(-1);
- X }
- X break;
- X }
- X
- X mailbox[0] = '\0';
- X if (i<argc)
- X strcpy(mailbox, argv[i]);
- X
- X if (mailbox[0] == '\0')
- X if (ptr = getenv("MAIL"))
- X (void) strcpy(mailbox, ptr);
- X else {
- X (void) strcpy(mailbox, getenv("HOME"));
- X (void) strcat(mailbox, "/mailbox");
- X }
- X
- X if (!strcmp("ck", argv[0]+strlen(argv[0])-2)) {
- X if ((c=check_box(mailbox, (out_device?out_device:stdout), verbose, false))==0)
- X printf("No new messages.\n");
- X exit(c);
- X }
- X
- X ppid = getppid();
- X if (fork())
- X exit(0);
- X
- X old_mtime = last_write(mailbox);
- X while(1) {
- X if (old_mtime < (curr=last_write(mailbox))) {
- X old_mtime = curr;
- X (void) check_box(mailbox, (out_device?out_device:stderr), verbose, true);
- X }
- X
- X sleep(interval);
- X
- X /* Check to see if parent has died (e.g., on logout).
- X * Commit suicide if it has.
- X * There must be a better way to do this! (setpgrp?)
- X */
- X if (kill(ppid, 0))
- X exit(0);
- X }
- X}
- X
- X
- X
- time_t last_write(fn)
- char *fn;
- X{
- X struct stat stbuf;
- X
- X stat(fn, &stbuf);
- X return((time_t) stbuf.st_mtime);
- X}
- X
- X
- X#define BUFSIZE 100
- X#define FROM_FIELD_LEN 19
- X#define SUBJ_FIELD_LEN 21
- X#if (FROM_FIELD_LEN != 19 || SUBJ_FIELD_LEN != 21)
- X HEY! Fix the fprintf() line below.
- X#endif
- X#if (BUFSIZE != 100)
- X HEY! Fix the fscanf() line below.
- X#endif
- X
- int check_box(fn, out_device, verbose, bell)
- char *fn;
- XFILE *out_device;
- boolean verbose, bell;
- X{
- X extern char *ctime();
- X void nonwhitecpy();
- X static char *margin =
- X "+---------------------------------------------+\n";
- X FILE *mbox;
- X char *devname;
- X char s[BUFSIZE], from_field[FROM_FIELD_LEN],
- X subj_field[SUBJ_FIELD_LEN];
- X int headers = 0, readstat = 0;
- X int count = 0;
- X
- X if (mbox = fopen(fn, "r")) {
- X while ((readstat=fscanf(mbox, "%100[^\n]", s)) != EOF) {
- X (void) getc(mbox);
- X
- X if (headers) {
- X if (readstat==0) {
- X headers = 0;
- X if (count==0)
- X fprintf(out_device, "%c%s",
- X (bell ? '\007' : '\0'), margin);
- X fprintf(out_device, "|%2d: %-18.18s{}%-20.20s |\n",
- X ++count, from_field, subj_field);
- X }
- X else if (!strncmp(s, "From:", 5))
- X nonwhitecpy(from_field, s+6, FROM_FIELD_LEN);
- X
- X else if (!strncmp(s, "Subject:", 8))
- X nonwhitecpy(subj_field, s+9, SUBJ_FIELD_LEN);
- X }
- X else if (!strncmp(s,"\001\001\001\001", 4)) {
- X headers = 1;
- X subj_field[0] = from_field[0] = '\0';
- X }
- X }
- X fclose(mbox);
- X if (count)
- X fprintf(out_device, margin);
- X }
- X else
- X verbose = true;
- X
- X if (verbose) {
- X struct stat stbuf;
- X
- X if (stat(fn, &stbuf))
- X perror(fn);
- X else
- X fprintf(out_device,
- X "[%s] Size: %d chars.\nLast modified: %s",
- X fn,
- X stbuf.st_size,
- X ctime((long *)&stbuf.st_mtime));
- X return(-1);
- X }
- X return(count);
- X
- X
- X}
- X
- X
- X
- void
- nonwhitecpy(d, s, dsize)
- register char *d, *s;
- int dsize;
- X{
- X register char *dend = d+dsize;
- X s--;
- X while (isspace(*++s));
- X while ((*d++ = *s++) && (d<dend));
- X}
- END_OF_FILE
- if test 4618 -ne `wc -c <'ck.c'`; then
- echo shar: \"'ck.c'\" unpacked with wrong size!
- fi
- # end of 'ck.c'
- fi
- if test -f 'ck.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ck.man'\"
- else
- echo shar: Extracting \"'ck.man'\" \(3012 characters\)
- sed "s/^X//" >'ck.man' <<'END_OF_FILE'
- X.TH CK 1L "4 February 1988" " " " "
- X
- X.SH NAME
- ck, ckd - report newly arrived mail
- X
- X.SH SYNOPSIS
- X.B ck
- X[
- X.B \-v
- X]
- X[
- X.B \-o
- X.I outfile
- X]
- X[
- X.I mailbox
- X]
- X.br
- X.B ckd
- X[
- X.B \-v
- X]
- X[
- X.B \-o
- X.I outfile
- X]
- X[
- X.BI \-i interval
- X]
- X[
- X.I mailbox
- X]
- X
- X.SH DESCRIPTION
- X.I ck
- and
- X.I ckd
- are, respectively, the command line and daemon versions of a program
- to monitor your incoming mail. They examine mailbox files and report
- the sender and subject of each message contained in the file. If a
- mailbox is not specified,
- X.I $HOME/mailbox
- will be used. If the user does not have read access to
- the mailbox, an attempt will be made to report the size of the
- file and when it was last modified. This allows the user to check
- if someone else recently received mail.
- X
- Although there are dozens of similar programs wandering around UNIX
- land, many don't work on common system configurations. (E.g.,
- X.I from
- only works if the mailbox lives in
- X.BR /usr/spool/mail "; "
- X.I biff
- and
- X.I rcvalert
- don't get along well with the SunView windows; etc.)
- X.I ck
- and
- X.I ckd
- contribute to this parochial mass, since currently they only work
- with MMDF format files (or more specifically, files in which
- each message is separated by a line containing four Control-A's).
- But they do try to be more flexible about how they notify the user.
- X
- X.I ck
- reports the status of the mailbox once and exits.
- X.I ckd
- runs in the background and reports whenever it notices that
- the mailbox has been modified.
- X.I ckd
- terminates automatically when it sees that the process from which it
- was invoked has also terminated. For example, if you run
- X.I ckd
- from your
- X.I .login
- file, it will terminate shortly after you logout.
- X
- X.I ck
- normally prints to the standard output, and
- X.I ckd
- to the standard error. This can be changed via the
- X.B \-o
- option described below.
- X.I ckd
- will try to ring the bell on the output device whenever it
- detects new mail.
- X
- X.SH OPTIONS
- X.TP
- X.B \-v
- After listing the contents of the mailbox, display its size and
- time of modification.
- X.TP
- X.BI \-o " outfile"
- Redirect output to the file or device specified by
- X.I outfile.
- If the file already exists, the output is appended to it.
- X.TP
- X.BI \-i interval
- Check the mailbox every
- X.I interval
- seconds instead of the default, 120. This option is only meaningful
- in
- X.IR ckd .
- X
- X.SH FILES
- X.TP
- X.B $HOME/mailbox
- default mailbox file to monitor
- X
- X.SH DIAGNOSTICS
- XExit status is -1 if the file specified in the
- X.B \-o
- option can't be opened. Otherwise,
- X.IR ck 's
- exit status is equal to the number of messages found in the
- mailbox, and
- X.IR ckd 's
- is 0.
- X
- X
- X.SH BUGS
- Only handles MMDF format files.
- X
- There should be an option to turn the bell on or off.
- X
- Ckd should be smarter about reporting changes in the file. Right
- now it announces any change which leaves messages in the file (even
- deleting some messages). A better approach would be to do some
- smart-work to see if it looks like new messages were added.
- X
- X.SH AUTHOR
- X
- Wayne Mesard, MESARD@BBN.COM
- X
- END_OF_FILE
- if test 3012 -ne `wc -c <'ck.man'`; then
- echo shar: \"'ck.man'\" unpacked with wrong size!
- fi
- # end of 'ck.man'
- fi
- if test -f 'ckd.man' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'ckd.man'\"
- else
- echo shar: Extracting \"'ckd.man'\" \(14 characters\)
- sed "s/^X//" >'ckd.man' <<'END_OF_FILE'
- X.so man1/ck.1
- END_OF_FILE
- if test 14 -ne `wc -c <'ckd.man'`; then
- echo shar: \"'ckd.man'\" unpacked with wrong size!
- fi
- # end of 'ckd.man'
- fi
- if test -f 'wsm_types.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'wsm_types.h'\"
- else
- echo shar: Extracting \"'wsm_types.h'\" \(437 characters\)
- sed "s/^X//" >'wsm_types.h' <<'END_OF_FILE'
- X/**
- X ** ADT: LIFO queue of int's
- X **/
- X
- X#ifndef LIFO_Q_SIZE
- X#define LIFO_Q_SIZE 20
- X#endif
- X
- typedef struct {
- X int q[LIFO_Q_SIZE];
- X int ptr;
- X} lifo;
- X
- X#define Q_init(QQ) QQ.ptr = 0
- X#define Q_pop(QQ) QQ.q[(--QQ.ptr)]
- X#define Q_peek(QQ) QQ.q[(QQ.ptr-1)]
- X#define Q_push(QQ, DATA) QQ.q[QQ.ptr]=DATA, QQ.ptr=((QQ.ptr+1)%LIFO_Q_SIZE)
- X#define Q_size(QQ) QQ.ptr
- X
- X
- X
- X/**
- X ** ADT: boolean
- X **/
- X
- X#define boolean short
- X#define true 1
- X#define false 0
- X
- X
- END_OF_FILE
- if test 437 -ne `wc -c <'wsm_types.h'`; then
- echo shar: \"'wsm_types.h'\" unpacked with wrong size!
- fi
- # end of 'wsm_types.h'
- fi
- echo shar: End of shell archive.
- exit 0
-